# -*- coding: utf-8 -*-
'''
@author: Johnny
@Created on: 2011-5-18
@version: 2011.5.18
@summary: Definition of xmlparser class
'''
import types, os
from xml.etree import ElementTree
from action.step import Step

class XmlParser(object):
    '''
    XML file related operation.
    '''
    def __init__(self, file):
        '''
        Constructor.
        @params:
        file -- xml file to write
        '''
        print 'xmlparse -- __init__ '
        self.file = file

    def indent(self, elem, level=0):
        '''
        Format xml files.
        Keyword arguments:
        elem -- xml element
        '''
        print 'xmlparse -- indent '
        i = "\n" + level * "\t"
        if len(elem):
            if not elem.text or not elem.text.strip():
                elem.text = i + "\t"
                
            if level and (not elem.tail or not elem.tail.strip()):
                elem.tail = i
                
            for elem in elem:
                self.indent(elem, level+1)

            if not elem.tail or not elem.tail.strip():
                elem.tail = i
        else:
            if level and (not elem.tail or not elem.tail.strip()):
                elem.tail = i    
        
    def write_xml_by_excel(self, case_list):
        '''
        Write case to xml file.
        @params:
        case_list -- case list
        file -- xml file to write
        '''
        print 'xmlparse -- write_xml_by_excel '
        
        try:
            # Create file and root element
            if os.path.exists(self.file):
                os.remove(self.file)
            f = open(self.file, 'a')
            f.write("<root>\n</root>")
            f.close()
    
            tree = ElementTree.parse(self.file)
            root = tree.getroot()
    
            # Write case information to xml tree
            for case in case_list:
                case_id = case[0]
                case_element = ElementTree.Element('case', {"id": str(case_id)})                   
                step_info_list = case[1]
                
                # Write step information to xml tree
                for step_info in step_info_list:
                    name = step_info.name
                    key = step_info.key
                    times = step_info.times
                    description = step_info.description
                    expected_result = step_info.expected_result
                    step_element = ElementTree.SubElement(case_element, 'step', 
                                                          {'stepnum': name}) 
                    key_element = ElementTree.SubElement(step_element, 
                                                         'stepexe', 
                                                         {'execute': key})
                    key_element.text = str(times)
                    description_element = ElementTree.SubElement(step_element, 
                                                                 'description')
                    description_element.text = str(description)
                    expected_result_element = \
                                     ElementTree.SubElement(step_element, 
                                                            'expected_result')
                    expected_result_element.text = str(expected_result)
                    
                    actions = step_info.actions
                    for action in actions:
                        action_name = action.name
                        action_value = action.value
                        
                        # Convert to string if value type is float
                        for value_index in range(len(action_value)):
                            if isinstance(action_value[value_index], (float)):
                                action_value[value_index] = \
                                str(int(action_value[value_index]))
                                
                        action_element = ElementTree.SubElement(step_element, 
                                                                'action', 
                                                        {'name': action_name})
                        for (value, num) in zip(action_value, 
                                                range(len(action_value))):
                            actionvalue_element = \
                            ElementTree.SubElement(action_element, 'value')
                            actionvalue_element.text = value 
                root.append(case_element)         
            self.indent(root)
            tree.write(self.file, encoding = "UTF-8")
        except Exception, e:
            print 'xmlparse -- write_xml_by_excel: Exception = ' + str(e)
        
    def read_case_from_xml(self):
        '''
        Read case from xml file.
        '''
        print 'xmlparse -- read_case_from_xml '
        
        try:
            tree = ElementTree.parse(self.file)
            case_list = tree.getiterator('case')
            case_info_list = []
            
            # Parse and get case from xml file
            for case in case_list:
                if ElementTree.iselement(case):
                    temp_case_info_list = []
                    case_id = case.attrib['id']
                    temp_case_info_list.append(case_id) 
                    
                    # Parse and get step from xml file
                    stp_list = case.getiterator('step')            
                    for stp in stp_list:
                        if ElementTree.iselement(stp):
                            step_info = Step('', '', '', '', '')
                            step_info.name = stp.attrib['stepnum']
                            stepexe_list = stp.getiterator('stepexe')
                            for stpexe in stepexe_list:
                                step_info.key = stpexe.attrib['execute']
                                step_info.times = stpexe.text
                            description_list = stp.getiterator('description')
                            for description in description_list:
                                step_info.description = description.text
                            expected_result_list = \
                                            stp.getiterator('expected_result')
                            for expected_result in expected_result_list:
                                step_info.expected_result = \
                                               expected_result.text
                            
                            # Parse and get action from xml file
                            action_info_list = stp.getiterator('action')
                            for action_info in action_info_list:
                                actionname = action_info.attrib['name'] 
                                actionvalue = []
                                value_info_list = \
                                               action_info.getiterator('value')
                                for value_info in value_info_list:
                                    value = value_info.text
                                    actionvalue.append(value)
                                step_info.add_action(actionname, actionvalue)                          
                            temp_case_info_list.append(step_info)
                case_info_list.append(temp_case_info_list)
            return case_info_list
        except Exception, e:
            print 'xmlparse -- read_case_from_xml: Exception = ' + str(e)
            return [] 
                        
    def write_xml_report(self, single_result_list): 
        '''
        Write case result to xml file.
        @params:
        single_result_list -- single case result list
        '''
        print 'xmlparse -- write_xml_report '
        
        try:
            if not os.path.exists(self.file):
                f = open(self.file, 'a')
                f.write("<root>\n</root>")
                f.close()
                 
            tree = ElementTree.parse(self.file)
            root = tree.getroot() 
            root.clear()
            print 'xmlparse -- write_xml_report: caseInfoList = ' + \
                  str(single_result_list)
            case_id = single_result_list.pop(0)
            case_result = single_result_list.pop(0)
            time_stamp = single_result_list.pop(0)
            step_info_list = single_result_list
            case_element = ElementTree.Element('case', {"id": str(case_id), 
                                                        'time_stamp': time_stamp})
                      
            for step_info in step_info_list:
                name = step_info.name
                key = step_info.key
                times = step_info.times
                description = step_info.description
                expected_result = step_info.expected_result
                step_element = ElementTree.SubElement(case_element, 'step', 
                                                      {'stepnum': name})
                key_element = ElementTree.SubElement(step_element, 
                                                         'stepexe', 
                                                         {'execute': key})
                key_element.text = str(times)
                description_element = ElementTree.SubElement(step_element, 
                                                             'description')
                description_element.text = str(description)
                expected_result_element = \
                                 ElementTree.SubElement(step_element, 
                                                        'expected_result')
                expected_result_element.text = str(expected_result)
                result_element = ElementTree.SubElement(step_element, 'result')
                result_element.text = step_info.result
                scrshot_element = ElementTree.SubElement(step_element, 
                                                             'screenshot')
                # If case result is failed
                if case_result:
                    scrshot_element.text = step_info.step_pic
            root.append(case_element)
            
            self.indent(root)       
            tree.write(self.file, encoding = "UTF-8")
        except Exception, e:
            print 'xmlparse -- write_xml_report: Exception = ' + str(e)
        
    def read_xml_report(self):
        '''
        Read case result from xml file.
        '''
        print 'xmlparse -- read_xml_report '
        
        try:
            tree = ElementTree.parse(self.file)
            case_list = tree.getiterator('case')
            print "xmlparse -- read_xml_report - case_list: " + str(case_list)
            result_list = []
            for case in case_list:
                if ElementTree.iselement(case):
                    case_id = case.attrib['id']
                    time_stamp = case.attrib['time_stamp'] 
                    result_list.append(case_id)
                    result_list.append(time_stamp) 
                    stp_list = case.getiterator('step')            
                    for stp in stp_list:
                        if ElementTree.iselement(stp):
                            step_info = Step('', '', '', '', '')
                            step_info.name = stp.attrib['stepnum']
                            stepexe_list = stp.getiterator('stepexe')
                            for stpexe in stepexe_list:
                                step_info.key = stpexe.attrib['execute']
                                step_info.times = stpexe.text
                            description_list = stp.getiterator('description')
                            for description in description_list:
                                step_info.description = description.text
                            expected_result_list = \
                                            stp.getiterator('expected_result')
                            for expected_result in expected_result_list:
                                step_info.expected_result = \
                                               expected_result.text
                            stepresult_list = stp.getiterator('result')
                            for result in stepresult_list:
                                step_info.result = result.text
                            stepshot_list = stp.getiterator('screenshot')
                            for scrshot in stepshot_list:
                                step_info.step_pic = scrshot.text
                        result_list.append(step_info)
            return result_list
        except Exception, e:
            print 'xmlparse -- read_xml_report: Exception = ' + str(e)
            return [] 